package controllers

import (
	"encoding/json"
	//"errors"
	"fmt"
	"github.com/astaxie/beego"
	"myapp/web/beegoapi/server/models"
	"strconv"
	"strings"
)

//oprations for book
type BookController struct {
	beego.Controller
}

func (this *BookController) URLMapping() {
	this.Mapping("Post", this.Post)
	this.Mapping("Get", this.Get)
	this.Mapping("GetAll", this.GetAll)
	this.Mapping("Put", this.Put)
	this.Mapping("Delete", this.Delete)
}

// @Title Post
// @Description Create Book
// @Param body body models.Book true "body for Book content"
// @Success 200
// @Failure 403 body is empty
// @router / [post]
func (this *BookController) Post() {
	var book models.Book
	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &book); err == nil {
		id, err := models.CreateBook(&book)
		if err != nil {
			this.Data["json"] = err.Error()
		} else {
			this.Data["json"] = fmt.Sprintf("Create book ok ，new book's id = %v", id)
		}
	}
	this.ServeJson()
}

// @Title GetAll
// @Description Get Book List
// @Param   query   query   string  false   "Filter. e.g. col1=v1,col2=v2 ..."
// @Param   fields  query   string  false   "Fields returned. e.g. col1,col2 ..."
// @Param	sortby	query	string	false	"Sorted-by fields. e.g. col1,col2 ..."
// @Param	order	query	string	false	"Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..."// @Param	limit	query	string	false	"Limit the size of result set. Must be an integer"
// @Param	limit	query	string	false	"Limit the size of result set. Must be an integer"
// @Param	offset	query	string	false	"Start position of result set. Must be an integer"
// @Success 200 {object} models.Book
// @Failure 403
// @router / [get]
func (this *BookController) GetAll() {

	var query map[string]string = make(map[string]string)
	var fields []string
	var sortby []string
	var order []string
	var offset int64 = 0
	var limit int64 = 10

	//query
	if v := this.GetString("query"); v != "" {
		for _, v2 := range strings.Split(v, ",") {
			kv := strings.Split(v2, "=")
			if len(kv) == 2 {
				query[kv[0]] = kv[1]
			} else {
				this.Data["json"] = "Error: invalid query key/value pair"
				this.ServeJson()
				return
			}
		}
	}

	//fields
	if v := this.GetString("fields"); v != "" {
		fields = strings.Split(v, ",")
	}
	//sortby
	if v := this.GetString("sortby"); v != "" {
		sortby = strings.Split(v, ",")
	}
	//order
	if v := this.GetString("order"); v != "" {
		order = strings.Split(v, ",")
	}
	//offset
	if v, err := this.GetInt64("offset"); err == nil {
		offset = v
	}
	//limit
	if v, err := this.GetInt64("limit"); err == nil {
		if v != 0 {
			limit = v
		}
	}

	books, err := models.GetBooks(query, fields, sortby, order, offset, limit)
	if err != nil {
		this.Data["json"] = err.Error()
	} else {
		if len(books) == 0 {
			this.Data["json"] = "Datebase no book !"
		} else {
			this.Data["json"] = books
		}
	}
	this.ServeJson()
}

// @Title Get
// @Description Get Book By Id
// @Param id path string true "The key for staticblock"
// @Success 200 {object} models.Book
// @Failure 403 :id is empty
// @router /:id [get]
func (this *BookController) Get() {
	idStr := this.Ctx.Input.Param(":id")
	id, _ := strconv.Atoi(idStr)
	book, err := models.GetBookById(id)
	if err != nil {
		this.Data["json"] = err.Error()
	} else {
		this.Data["json"] = book
	}
	this.ServeJson()
}

// @Title Put
// @Description Update Book By Id
// @Param id   path string      true "The id you want to update"
// @Param body body models.Book true "body for Category content"
// @Success 200
// @Failure 403 body is empty
// @router /:id [put]
func (this *BookController) Put() {
	id, _ := strconv.Atoi(this.Ctx.Input.Param(":id"))
	var book models.Book
	book.Id = id
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &book)
	if err == nil {
		err := models.UpdateBookById(&book)
		if err != nil {
			this.Data["json"] = err.Error()
		} else {
			this.Data["json"] = "Update Book OK"
		}
	} else {
		this.Data["json"] = "body is null/error"
	}
	this.ServeJson()
}

// @Title Delete
// @Description Delete Book By Id
// @Param id   path string      true "The id you want to delete"
// @Success 200
// @Failure 403 body is empty
// @router /:id [delete]
func (this *BookController) Delete() {
	id, _ := strconv.Atoi(this.Ctx.Input.Param(":id"))
	err := models.DeleteBookById(id)
	if err != nil {
		this.Data["json"] = err.Error()
	} else {
		this.Data["json"] = "Delete Book OK"
	}
	this.ServeJson()
}
